from api_push.orders_push import OrdersPush
from api_push.search_kws_push import Search_Kws_Push
from loguru import logger
from pipei_data import pipei_desc
from plugin.is_renewed_count import Renewed_count
from tools.base_tools import getdays, generate_dates_from_offset, generate_date_range
from db_tools import MysqlTool
from apscheduler.schedulers.blocking import BlockingScheduler
import argparse
from datetime import datetime


def get_last_sync_date(table_name, date_column='create_time_format', default_days=30):
    """
    获取数据同步的起始日期
    
    Args:
        table_name (str): 表名
        date_column (str): 日期字段名
        default_days (int): 数据为空时，从多少天前开始全量同步
    
    Returns:
        str: 起始同步日期 (YYYY-MM-DD)
    """
    try:
        with MysqlTool() as db_tool:
            max_date = db_tool.get_max_date(table_name, date_column)
            if max_date:
                logger.info(f"数据库 {table_name} 表最新日期: {max_date.strftime('%Y-%m-%d')}")
                return max_date.strftime('%Y-%m-%d')
            else:
                default_start = getdays(default_days).strftime('%Y-%m-%d')
                logger.info(f"数据库 {table_name} 表为空，从 {default_days} 天前开始全量同步: {default_start}")
                return default_start
    except Exception as e:
        logger.error(f"获取最新同步日期失败: {e}")
        # 出错时使用默认值
        default_start = getdays(default_days).strftime('%Y-%m-%d')
        logger.info(f"使用默认起始日期: {default_start}")
        return default_start


def start_incremental():
    """
    增量同步模式：从数据库最新记录开始同步到昨天
    """
    logger.info("=== 开始增量数据同步 ===")
    
    # 获取订单表的最新日期
    order_start_date = get_last_sync_date('pay', 'create_time_format')
    # 获取搜索词表的最新日期  
    search_start_date = get_last_sync_date('search_kws', 'day_str')
    
    # 结束日期都是昨天
    end_date = getdays(1).strftime('%Y-%m-%d')
    
    # 同步订单数据
    if order_start_date <= end_date:
        order_day_list = generate_date_range(order_start_date, end_date)
        for day_str in order_day_list:
            logger.info(f"增量更新订单,{day_str}")
            order_push = OrdersPush(day_str, day_str, "pay")
            order_push.push_mysql()
    else:
        logger.info("订单数据已是最新，无需同步")
    
    # 同步搜索词数据
    if search_start_date <= end_date:
        search_day_list = generate_date_range(search_start_date, end_date)
        for day_str in search_day_list:
            logger.info(f"增量更新搜索词,{day_str}")
            push_kws = Search_Kws_Push(day_str, day_str, "search_kws")
            push_kws.push_mysql()
    else:
        logger.info("搜索词数据已是最新，无需同步")
    
    # 更新匹配数据和续费信息
    try:
        logger.info("🧩 开始更新匹配数据(详情)...")
        # 使用并发版本提升性能
        success_count, error_count = pipei_desc.start_concurrent(max_workers=6)
        if error_count == 0:
            logger.info("✅ 匹配数据更新完成")
        else:
            logger.warning(f"⚠️  匹配数据更新完成，但有 {error_count} 条记录处理失败")
    except Exception as e:
        logger.error(f"❌ 匹配数据更新失败: {e}")
        # 如果并发版本失败，尝试使用原始版本
        logger.info("🔄 尝试使用串行版本...")
        try:
            pipei_desc.start()
            logger.info("✅ 串行版本匹配数据更新完成")
        except Exception as e2:
            logger.error(f"❌ 串行版本也失败: {e2}")
    
    # 更新续费信息
    try:
        logger.info("💳 开始更新续费信息(并发版本)...")
        success_count, error_count = Renewed_count().update_many_concurrent(max_workers=6)
        if error_count == 0:
            logger.info("✅ 续费信息更新完成")
        else:
            logger.warning(f"⚠️  续费信息更新完成，但有 {error_count} 条记录处理失败")
    except Exception as e:
        logger.error(f"❌ 并发续费信息更新失败: {e}")
        # 如果并发版本失败，尝试使用原始版本
        logger.info("🔄 尝试使用串行版本...")
        try:
            Renewed_count().update_many()
            logger.info("✅ 串行版本续费信息更新完成")
        except Exception as e2:
            logger.error(f"❌ 串行版本也失败: {e2}")
    
    logger.info("=== 增量数据同步完成 ===")


def start_override(days=7, delete_before_sync=True):
    """
    覆盖同步模式：指定天数范围，可选择是否先删除数据
    
    Args:
        days (int): 同步最近N天的数据
        delete_before_sync (bool): 是否在同步前删除现有数据
    """
    logger.info(f"🚀 === 开始覆盖同步模式 (最近{days}天) ===")
    
    try:
        # 计算日期范围
        logger.info("📅 计算同步日期范围...")
        start_date = getdays(days).strftime('%Y-%m-%d')
        end_date = getdays(1).strftime('%Y-%m-%d')
        
        logger.info(f"📊 同步日期范围: {start_date} 到 {end_date}")
        
        # 如果需要删除现有数据
        if delete_before_sync:
            logger.info("🗑️  开始删除现有数据...")
            try:
                with MysqlTool() as db_tool:
                    logger.info("正在删除订单表(pay)数据...")
                    db_tool.delete_data_by_date_range('pay', 'create_time_format', start_date, end_date)
                    
                    logger.info("正在删除搜索词表(search_kws)数据...")
                    db_tool.delete_data_by_date_range('search_kws', 'day_str', start_date, end_date)
                    
                logger.info("✅ 数据删除完成")
            except Exception as e:
                logger.error(f"❌ 删除数据时出错: {e}")
                logger.info("⚠️  继续执行同步，可能会有重复数据")
        else:
            logger.info("📝 跳过删除步骤，将进行增量更新")
        
        # 生成同步日期列表
        logger.info("🔄 生成同步日期列表...")
        day_list = generate_date_range(start_date, end_date)
        logger.info(f"📋 需要同步的日期列表: {day_list}")
        
        # 同步订单数据和搜索词数据
        total_days = len(day_list)
        for i, day_str in enumerate(day_list, 1):
            logger.info(f"📦 [{i}/{total_days}] 开始同步 {day_str} 的数据...")
            
            # 同步订单数据
            try:
                logger.info(f"💰 正在同步订单数据: {day_str}")
                order_push = OrdersPush(day_str, day_str, "pay")
                result = order_push.push_mysql()
                if result:
                    logger.info(f"✅ 订单数据同步成功: {day_str}")
                else:
                    logger.warning(f"⚠️  订单数据同步可能有问题: {day_str}")
            except Exception as e:
                logger.error(f"❌ 订单数据同步失败 {day_str}: {e}")
            
            # 同步搜索词数据
            try:
                logger.info(f"🔍 正在同步搜索词数据: {day_str}")
                push_kws = Search_Kws_Push(day_str, day_str, "search_kws")
                result = push_kws.push_mysql()
                if result:
                    logger.info(f"✅ 搜索词数据同步成功: {day_str}")
                else:
                    logger.warning(f"⚠️  搜索词数据同步可能有问题: {day_str}")
            except Exception as e:
                logger.error(f"❌ 搜索词数据同步失败 {day_str}: {e}")
                
            logger.info(f"✨ [{i}/{total_days}] {day_str} 同步完成")
        
        logger.info("🔗 开始后续处理...")
        
        # 更新匹配数据和续费信息
        try:
            logger.info("🧩 开始更新匹配数据(详情)...")
            # 使用并发版本提升性能
            success_count, error_count = pipei_desc.start_concurrent(max_workers=6)
            if error_count == 0:
                logger.info("✅ 匹配数据更新完成")
            else:
                logger.warning(f"⚠️  匹配数据更新完成，但有 {error_count} 条记录处理失败")
        except Exception as e:
            logger.error(f"❌ 匹配数据更新失败: {e}")
            # 如果并发版本失败，尝试使用原始版本
            logger.info("🔄 尝试使用串行版本...")
            try:
                pipei_desc.start()
                logger.info("✅ 串行版本匹配数据更新完成")
            except Exception as e2:
                logger.error(f"❌ 串行版本也失败: {e2}")
        
        try:
            logger.info("💳 开始更新续费信息(并发版本)...")
            success_count, error_count = Renewed_count().update_many_concurrent(max_workers=6)
            if error_count == 0:
                logger.info("✅ 续费信息更新完成")
            else:
                logger.warning(f"⚠️  续费信息更新完成，但有 {error_count} 条记录处理失败")
        except Exception as e:
            logger.error(f"❌ 并发续费信息更新失败: {e}")
            # 如果并发版本失败，尝试使用原始版本
            logger.info("🔄 尝试使用串行版本...")
            try:
                Renewed_count().update_many()
                logger.info("✅ 串行版本续费信息更新完成")
            except Exception as e2:
                logger.error(f"❌ 串行版本也失败: {e2}")
        
        logger.info("🎉 === 覆盖同步完成 ===")
        
    except Exception as e:
        logger.error(f"💥 覆盖同步过程中发生严重错误: {e}")
        logger.error("🚨 请检查网络连接、数据库配置和API可用性")
        raise


def start_custom_range(start_date, end_date, delete_before_sync=True):
    """
    自定义日期范围同步模式：指定具体的开始和结束日期
    
    Args:
        start_date (str): 开始日期 (YYYY-MM-DD)
        end_date (str): 结束日期 (YYYY-MM-DD)
        delete_before_sync (bool): 是否在同步前删除现有数据
    """
    logger.info(f"🎯 === 开始自定义日期范围同步 ===")
    logger.info(f"📅 指定日期范围: {start_date} 到 {end_date}")
    
    try:
        # 验证日期格式
        from datetime import datetime
        try:
            start_dt = datetime.strptime(start_date, '%Y-%m-%d')
            end_dt = datetime.strptime(end_date, '%Y-%m-%d')
            logger.info("✅ 日期格式验证通过")
        except ValueError as e:
            logger.error(f"❌ 日期格式错误: {e}")
            logger.error("📝 请使用 YYYY-MM-DD 格式，例如: 2024-01-23")
            return False
        
        # 检查日期逻辑
        if start_dt > end_dt:
            logger.error("❌ 开始日期不能晚于结束日期")
            return False
        
        # 计算日期范围
        date_diff = (end_dt - start_dt).days + 1
        logger.info(f"📊 共需同步 {date_diff} 天的数据")
        
        # 如果需要删除现有数据
        if delete_before_sync:
            logger.info("🗑️  开始删除指定日期范围的现有数据...")
            try:
                with MysqlTool() as db_tool:
                    logger.info(f"正在删除订单表(pay)数据: {start_date} ~ {end_date}")
                    db_tool.delete_data_by_date_range('pay', 'create_time_format', start_date, end_date)
                    
                    logger.info(f"正在删除搜索词表(search_kws)数据: {start_date} ~ {end_date}")
                    db_tool.delete_data_by_date_range('search_kws', 'day_str', start_date, end_date)
                    
                logger.info("✅ 指定范围数据删除完成")
            except Exception as e:
                logger.error(f"❌ 删除数据时出错: {e}")
                logger.info("⚠️  继续执行同步，可能会有重复数据")
        else:
            logger.info("📝 跳过删除步骤，将进行覆盖更新")
        
        # 生成同步日期列表
        logger.info("🔄 生成同步日期列表...")
        day_list = generate_date_range(start_date, end_date)
        logger.info(f"📋 需要同步的日期列表: {day_list}")
        
        # 同步数据
        total_days = len(day_list)
        success_count = 0
        error_count = 0
        
        for i, day_str in enumerate(day_list, 1):
            logger.info(f"📦 [{i}/{total_days}] 开始同步 {day_str} 的数据...")
            day_success = True
            
            # 同步订单数据
            try:
                logger.info(f"💰 正在同步订单数据: {day_str}")
                order_push = OrdersPush(day_str, day_str, "pay")
                result = order_push.push_mysql()
                if result:
                    logger.info(f"✅ 订单数据同步成功: {day_str}")
                else:
                    logger.warning(f"⚠️  订单数据同步可能有问题: {day_str}")
                    day_success = False
            except Exception as e:
                logger.error(f"❌ 订单数据同步失败 {day_str}: {e}")
                day_success = False
            
            # 同步搜索词数据
            try:
                logger.info(f"🔍 正在同步搜索词数据: {day_str}")
                push_kws = Search_Kws_Push(day_str, day_str, "search_kws")
                result = push_kws.push_mysql()
                if result:
                    logger.info(f"✅ 搜索词数据同步成功: {day_str}")
                else:
                    logger.warning(f"⚠️  搜索词数据同步可能有问题: {day_str}")
                    day_success = False
            except Exception as e:
                logger.error(f"❌ 搜索词数据同步失败 {day_str}: {e}")
                day_success = False
            
            if day_success:
                success_count += 1
                logger.info(f"✨ [{i}/{total_days}] {day_str} 同步完成")
            else:
                error_count += 1
                logger.warning(f"⚠️  [{i}/{total_days}] {day_str} 同步有问题")
        
        # 显示同步统计
        logger.info(f"📈 同步统计: 成功 {success_count} 天, 异常 {error_count} 天")
        
        logger.info("🔗 开始后续处理...")
        
        # 更新匹配数据和续费信息
        try:
            logger.info("🧩 开始更新匹配数据(详情)...")
            # 使用并发版本提升性能
            match_success, match_error = pipei_desc.start_concurrent(max_workers=6)
            if match_error == 0:
                logger.info("✅ 匹配数据更新完成")
            else:
                logger.warning(f"⚠️  匹配数据更新完成，但有 {match_error} 条记录处理失败")
        except Exception as e:
            logger.error(f"❌ 匹配数据更新失败: {e}")
            # 如果并发版本失败，尝试使用原始版本
            logger.info("🔄 尝试使用串行版本...")
            try:
                pipei_desc.start()
                logger.info("✅ 串行版本匹配数据更新完成")
            except Exception as e2:
                logger.error(f"❌ 串行版本也失败: {e2}")
        
        try:
            logger.info("💳 开始更新续费信息(并发版本)...")
            success_count, error_count = Renewed_count().update_many_concurrent(max_workers=6)
            if error_count == 0:
                logger.info("✅ 续费信息更新完成")
            else:
                logger.warning(f"⚠️  续费信息更新完成，但有 {error_count} 条记录处理失败")
        except Exception as e:
            logger.error(f"❌ 并发续费信息更新失败: {e}")
            # 如果并发版本失败，尝试使用原始版本
            logger.info("🔄 尝试使用串行版本...")
            try:
                Renewed_count().update_many()
                logger.info("✅ 串行版本续费信息更新完成")
            except Exception as e2:
                logger.error(f"❌ 串行版本也失败: {e2}")
        
        if error_count == 0:
            logger.info("🎉 === 自定义日期范围同步完成 (全部成功) ===")
        else:
            logger.warning(f"⚠️  === 自定义日期范围同步完成 (有 {error_count} 天同步异常) ===")
        
        return error_count == 0
        
    except Exception as e:
        logger.error(f"💥 自定义日期范围同步过程中发生严重错误: {e}")
        logger.error("🚨 请检查网络连接、数据库配置和API可用性")
        raise


def start(offset=0):
    # 基于昨日的数据,生成对应的时间线 offset 只推迟1天
    # 昨天1,今天0
    day_str_list = generate_dates_from_offset(str(getdays(1)), offset)

    for day_str in day_str_list:
        logger.info(f"开始更新订单,{day_str}")
        order_push = OrdersPush(day_str, day_str, "pay")
        order_push.push_mysql()

        logger.info(f"开始更新搜索词,{day_str}")
        push_kws = Search_Kws_Push(day_str, day_str, "search_kws")
        push_kws.push_mysql()

    # 更新匹配数据和续费信息
    try:
        logger.info("🧩 开始更新匹配数据(详情)...")
        # 使用并发版本提升性能
        success_count, error_count = pipei_desc.start_concurrent(max_workers=6)
        if error_count == 0:
            logger.info("✅ 匹配数据更新完成")
        else:
            logger.warning(f"⚠️  匹配数据更新完成，但有 {error_count} 条记录处理失败")
    except Exception as e:
        logger.error(f"❌ 匹配数据更新失败: {e}")
        # 如果并发版本失败，尝试使用原始版本
        logger.info("🔄 尝试使用串行版本...")
        try:
            pipei_desc.start()
            logger.info("✅ 串行版本匹配数据更新完成")
        except Exception as e2:
            logger.error(f"❌ 串行版本也失败: {e2}")

    # 更新续费信息
    try:
        logger.info("💳 开始更新续费信息(并发版本)...")
        success_count, error_count = Renewed_count().update_many_concurrent(max_workers=6)
        if error_count == 0:
            logger.info("✅ 续费信息更新完成")
        else:
            logger.warning(f"⚠️  续费信息更新完成，但有 {error_count} 条记录处理失败")
    except Exception as e:
        logger.error(f"❌ 并发续费信息更新失败: {e}")
        # 如果并发版本失败，尝试使用原始版本
        logger.info("🔄 尝试使用串行版本...")
        try:
            Renewed_count().update_many()
            logger.info("✅ 串行版本续费信息更新完成")
        except Exception as e2:
            logger.error(f"❌ 串行版本也失败: {e2}")


if __name__ == "__main__":
    # 添加命令行参数解析
    parser = argparse.ArgumentParser(description='素材BI数据同步系统')
    parser.add_argument('--mode', choices=['incremental', 'override', 'range', 'schedule', 'legacy'], 
                        default='schedule', help='同步模式')
    parser.add_argument('--days', type=int, default=7, 
                        help='覆盖模式下同步的天数 (默认7天)')
    parser.add_argument('--start-date', type=str, 
                        help='自定义日期范围模式的开始日期 (YYYY-MM-DD)')
    parser.add_argument('--end-date', type=str, 
                        help='自定义日期范围模式的结束日期 (YYYY-MM-DD)')
    parser.add_argument('--no-delete', action='store_true', 
                        help='不删除现有数据，直接覆盖更新')
    
    args = parser.parse_args()
    
    if args.mode == 'incremental':
        # 增量同步模式
        start_incremental()
    elif args.mode == 'override':
        # 覆盖同步模式
        delete_before_sync = not args.no_delete
        start_override(days=args.days, delete_before_sync=delete_before_sync)
    elif args.mode == 'range':
        # 自定义日期范围同步模式
        if not args.start_date or not args.end_date:
            print("❌ 错误: 自定义日期范围模式需要同时指定 --start-date 和 --end-date")
            print("📝 示例: python run.py --mode range --start-date 2024-01-20 --end-date 2024-01-22")
            exit(1)
        
        delete_before_sync = not args.no_delete
        start_custom_range(args.start_date, args.end_date, delete_before_sync=delete_before_sync)
    elif args.mode == 'legacy':
        # 兼容原有逻辑
        start(0)
    else:
        # 默认定时任务模式（使用增量同步）
        DEBUG = 0
        if DEBUG:
            start_incremental()
        else:
            scheduler = BlockingScheduler()
            
            # 定时任务使用增量同步
            scheduler.add_job(
                start_incremental, "cron", hour=5, minute=0, 
                max_instances=100, misfire_grace_time=60
            )
            
            try:
                print("开始执行定时任务 (增量同步模式)")
                scheduler.start()
            except (KeyboardInterrupt, SystemExit):
                print("程序被中断退出")
                pass